﻿using System.Web;
using HynuIOTA.Entity;
using HynuIOTA.Web.Helpers;
using Microsoft.Win32;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace HynuIOTA.Web.Areas.Users.Controllers
{
    using HynuIOTA.Common.Attribute;
    using HynuIOTA.Entity.FormatEntity;
    using HynuIOTA.Entity.ViewEntitys;
    using HynuIOTA.Helpers;
    using HynuIOTA.Web.Controllers;
    using HynuIOTA.Web.Models;
    using System;
    using System.Data;
    using System.Data.Entity;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Threading.Tasks;
    using System.Web.Mvc;
    using static HynuIOTA.Common.StringConst;

    public class UserController : BaseController
    {
        #region Login
        /// <summary>
        /// GET: Users/User/Login
        /// 登录页面
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [SkipLogin]
        public async Task<ActionResult> Login()
        {
            if (Request["goto"] != null)
            {
                OpContext.Session["Path"] = Request["goto"];
            }
            else
            {
                var backUrl = Request.UrlReferrer?.ToString();
                if (backUrl != null)
                {
                    OpContext.Session["Path"] = backUrl.Contains("Login") ? null : backUrl;
                }
            }
            await OperationContext.CheckRememberUser(OpContext);

            if (OpContext.Session[nameof(User)] != null)
            {
                return Redirect(Url.Action("Index", "Home", new { area = string.Empty }));
            }
            return View();
        }

        /// <summary>
        /// POST: Users/User/Login
        /// 登录请求处理
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [SkipLogin]
        public async Task<ActionResult> Login(Entity.ViewEntitys.LoginViewModel login)
        {
            // 检测模型转换是否正确
            if (ModelState.IsValid == false)
            {
                return JsMsg("提交错误!", Url.Position(nameof(Login)));
            }

            // 检测验证码是否正确
            if (!OpContext.CheckValidateCode(login.validateCode))
            {
                OpContext.Session[nameof(Entity.ViewEntitys.LoginViewModel.validateCode)] = null;
                return JsMsg("验证码错误!", Url.Position(nameof(Login)));
            }

            // 检测用户名或密码是否正确
            var userInfo = await OpContext.Service.User.Where(u => u.UserName == login.userName
                        && u.UserPassword == login.userPassword && u.IsDel == false).FirstOrDefaultAsync();
            if (userInfo == null)
            {
                return JsMsg("用户名或密码错误!", Url.Position(nameof(Login)));
            }

            // 加入Session中
            OpContext.Session.Timeout = 60;
            var relo = userInfo.Relo.Select(r => new Relo { Id = r.Id, Description = r.Description, Action = r.Action.Select(a => a.ToPOCO()).ToList() }).ToList();
            var userPoco= userInfo.ToPOCO();
            userPoco.Relo = relo;
            OpContext.Session.Add(nameof(User), userPoco);

            if (login.rememberPassword == "on")
            {
                OperationContext.RememberUser(userInfo, OpContext.Response);
            }

            string backUrl = OpContext.Session["Path"] as string;
            if (backUrl == null)
            {
                backUrl = Url.Action("Index", "Home");
            }
            else
            {
                OpContext.Session["Path"] = null;
            }

            userInfo.LastLoginIP = Tools.GetUserIp();
            userInfo.LastLoginTime = DateTime.Now;

            OpContext.Service.SaveChangesAsync().Forget();
            // 返回登录成功
            return JsMsg("登录成功！", backUrl);
        }
        #endregion

        #region 编辑登录用户
        /// <summary>
        /// 编辑用户信息
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ActionResult> EditUser()
        {
            if (OpContext.UserEntity == null)
            {
                return OpContext.JsMsg(USER_NOLOGIN_ERROR, UrlConst.USER_LOGIN);
            }

            var user = await OpContext.Service.User.Where(u => u.Id == OpContext.UserEntity.Id).FirstOrDefaultAsync();
            if (user == null)
            {
                return OpContext.JsMsg(USER_USERNOEXIST_ERROR, UrlConst.USER_LOGIN);
            }

            ViewBag.user = user;
            return View();
        }

        /// <summary>
        /// 更改用户
        /// </summary>
        /// <param name="userViewModel"></param>
        /// <returns></returns>
        [HttpPut]
        [AjaxRequest]
        public async Task<ActionResult> PutUser(PutCurrentUserViewModel userViewModel)
        {
            if (OpContext.UserEntity == null)
            {
                return OpContext.JsMsg(USER_NOLOGIN_ERROR, UrlConst.USER_LOGIN);
            }

            var user = await OpContext.Service.User.Where(u => u.Id == OpContext.UserEntity.Id).FirstOrDefaultAsync();
            if (user == null)
            {
                return OpContext.JsMsg(USER_USERNOEXIST_ERROR, UrlConst.USER_LOGIN);
            }

            Tools.SetValues(user, userViewModel, ModelState.Keys.ToArray());

            var result = await OpContext.SaveChangesAsync();
            return result ?? OpContext.JsonMsgOK(DATA_MODIFY_SUCCESS);
        }
        #endregion

        /// <summary>
        /// GET: Users/User/ChangePassword
        /// 更改密码功能
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult ChangePassword()
        {
            return View();
        }

        /// <summary>
        /// POST: Users/User/ChangePassword
        /// 更改密码
        /// </summary>
        /// <param name="changePasswordViewModel"></param>
        /// <returns></returns>
        [HttpPut]
        [AjaxRequest]
        public async Task<ActionResult> ChangePassword(ChangePasswordViewModel changePasswordViewModel)
        {
            if (ModelState.IsValid == false)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
            }

            var user = await OpContext.Service.User.Where(u => u.Id == OpContext.UserEntity.Id).FirstOrDefaultAsync();
            if (changePasswordViewModel.oldPassword != user.UserPassword)
            {
                return OpContext.JsonMsgFail(CHECK_PASSWORD_ERROR);
            }
            // 因为这是被ChangeTracker所追踪的实体，所以不需要单独改变其State状态，直接保存更改即可
            user.UserPassword = changePasswordViewModel.newPassword;
            try
            {
                if (await OpContext.Service.SaveChangesAsync() < 1)
                {
                    return OpContext.JsonMsgErr(DATA_SAVECHANGES_ERROR);
                }
            }
            catch (Exception ex)
            {
                return OpContext.JsonMsgFail(ex.Message);
            }

            OpContext.LoginOut();
            return OpContext.JsonMsgOK(DATA_MODIFY_SUCCESS, UrlConst.USER_LOGIN);
        }

        #region 注册用户
        /// <summary>
        /// GET: Users/User/Register
        /// 注册用户
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [SkipLogin]
        public ActionResult Register()
        {
            return View();
        }

        /// <summary>
        /// ANY: Users/User/IsRegister
        /// 检查用户名或email是否被注册
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [SkipLogin]
        public ActionResult IsRegister(Entity.User user)
        {
            return CheckUserIsRepeat(user) ? JsonMsgFail() : JsonMsgOK();
        }

        /// <summary>
        /// POST: Users/User/Register
        /// 注册用户
        /// </summary>
        /// <param name="user"></param>
        /// <param name="validateCode"></param>
        /// <returns></returns>
        [HttpPost]
        [SkipLogin]
        public async Task<ContentResult> Register(Entity.User user, string validateCode)
        {
            // 检查验证码
            if (!OpContext.CheckValidateCode(validateCode))
            {
                return JsMsg("验证码错误!", Url.Position(nameof(Register)));
            }

            // 检查必填字段是否填写
            if (!ModelState.IsValidField(user.UserName) || !ModelState.IsValidField(user.UserPassword) || !ModelState.IsValidField(user.Email))
            {
                return JsMsg("必填字段未填写！", Url.Position(nameof(Register)));
            }

            // 检查必填字段是否正确
            if (!FieldCheckHelper.IsEmail(user.Email))
            {
                return JsMsg("Email不合法!", Url.Position(nameof(Register)));
            }

            // 检查用户字段是否重复
            if (CheckUserIsRepeat(user))
            {
                return JsMsg("用户字段重复！", Url.Position(nameof(Register)));
            }

            user.CreateTime = DateTime.Now;
            user.LastLoginTime = DateTime.Now;
            user.LastLoginIP = Tools.GetUserIp();

            OpContext.Service.User.Add(user);
            await OpContext.Service.SaveChangesAsync();

            return JsMsg("注册成功!", Url.Position(nameof(Login)));
        }

        /// <summary>
        /// 检查用户关键属性是否重复
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        private bool CheckUserIsRepeat(Entity.User user)
        {
            // 检查用户名是否重复
            if (ModelState.IsValidField(nameof(Entity.User.UserName)))
            {
                if (CheckFieldIsRepeat(OpContext.Service.User, u => u.UserName == user.UserName))
                    return true;
            }

            // 检查Email是否重复
            if (ModelState.IsValidField(nameof(Entity.User.Email)))
            {
                if (CheckFieldIsRepeat(OpContext.Service.User, u => u.Email == user.Email))
                    return true;
            }

            // 检查QQ号是否重复
            if (ModelState.IsValidField(nameof(Entity.User.QQNum)))
            {
                if (CheckFieldIsRepeat(OpContext.Service.User, u => u.QQNum == user.QQNum))
                    return true;
            }

            return false;
        }

        /// <summary>
        /// 检查某个字段是否重复
        /// </summary>
        /// <returns>重复为:true 不重复为:false</returns>
        private static bool CheckFieldIsRepeat<T>(IService.IServiceBase<T> service, Expression<Func<T, bool>> expression) where T : class, new()
        {
            return service.Where(expression).Any();
        }
        #endregion

        #region 注销用户
        /// <summary>
        /// ANY: Users/User/LoginOut
        /// 注销登录
        /// </summary>
        /// <returns></returns>
        [SkipPermission]
        public ActionResult LoginOut()
        {
            OpContext.LoginOut();
            return JsMsg("注销成功！", Url.Position<HomeController>(nameof(HomeController.Index)));
        }
        #endregion

        /// <summary>
        /// ANY: Users/User/GetUserList
        /// 获取用户列表
        /// </summary>
        /// <param name="paging"></param>
        /// <returns></returns>
        [AjaxRequest]
        public async Task<ActionResult> GetUserList(PagingViewModel paging)
        {
            // 验证字段是否通过
            if (ModelState.IsValid == false)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
            }

            // 构建pageData类
            var pageData = new PageData() { PageIndex = paging.page, PageSize = paging.rows };
            // 查询数据
            var pageList = await OpContext.Service.User.WherePage(
                pageData,
                u => true,
                u => u.CreateTime,
                false
            ).ToListAsync();

            // 返回数据
            return OpContext.JsonMsgOK(data: new { tatol = pageData.PageCount, rows = pageList.Select(u => u.ToPOCO()) });
        }

        /// <summary>
        /// ANY: Users/User/DeleUser
        /// 删除用户
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [AjaxRequest]
        public async Task<ActionResult> DeleUser(int? id)
        {
            if (id == null)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
            }

            // 查找ID是否存在
            var user = await OpContext.Service.User.Where(u => u.Id == id).FirstOrDefaultAsync();
            if (user == null)
            {
                return OpContext.JsonMsgFail(DATA_NOEXIST_ERROR);
            }

            // 软删除用户，保存更改
            try
            {
                user.IsDel = true;
                await OpContext.Service.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                return OpContext.JsonMsgErr(ex.Message);
            }

            return OpContext.JsonMsgOK(DATA_DELECT_SUCCESS);
        }
    }
}